#include <ClanLib/core.h>
#include <ClanLib/display.h>

#include "Rullo.h"

Rullo::Rullo()
{
	// risorse è un CL_ResourceManager utilizzato per la gestione del file .xml che caratterizza le risorse del gioco
	risorse=new CL_ResourceManager("risorse.xml");

	// copertura (inf e sup) sono le immagini che nascondono i simboli quando escono dai rulli
	coperturainf = new CL_Surface(IMM_COPERTURA, risorse);
	coperturasup = new CL_Surface(IMM_COPERTURA, risorse);

	// cella è l'immagine del rullo
	cella=new CL_Surface(IMM_RULLO, risorse);

	// Riempio il vettore_simboli con tutti i simboli definiti in risorse.xml
	// sotto la sezione Simboli_Rullo , associando Nome a ID
	// il vettore è ordinato secondo l'ID
	RiempiVettoreSimboli();

	// Setto le variabili bool che mi indicano l'inizio del gioco e lo scorrimento del rullo
	inizio=true;
	stop=true;
}

Rullo::~Rullo()
{
	delete simboli1;
	delete simboli2;
	delete simboli3;
	delete simboliAPP;
	delete coperturainf;
	delete coperturasup;
	delete cella;
	delete risorse;
}

void Rullo::RiempiVettoreSimboli()
{
	int i, ID;
	std::string Nome;
	// Variabili utilizzate per la gestione degli elementi di risorse.xml
	CL_DomElement element;
	CL_Resource risorsa_dett;

	// Vettore che mi identifica tutti i tag "sprite" sotto la sezione "Simboli_Rullo" di risorse.xml
	std::vector<std::string> v = risorse->get_resources_of_type("sprite","Simboli_Rullo");
	std::vector<std::string>::iterator it;

	// Ciclo che mi permette di scandagliare tutti gli elementi del vettore degli sprite
	for(i=0, it = v.begin(); it!=v.end(); ++it , i++)
	{
		std::string Sezione="Simboli_Rullo/";
		risorsa_dett=risorse->get_resource(*it);
		risorsa_dett.load();
		element=risorsa_dett.get_element();
		// Riempio ID e Nome secondo i tag degli elementi di risorse.xml
		ID=CL_String::to_int(element.get_attribute("id"));
		Nome=element.get_attribute("name");

		// La stringa Sezione sarà "Simboli_Rullo/(nome del simbolo)"
		Sezione.append(Nome);

		// Infine iserisco i dati presi in risorse.xml nel vettore dei simboli
		vettore_simboli[ID].ID=ID;
		vettore_simboli[ID].Nome=Sezione;
	}
}

int Rullo::TornaDimOriz()
{
	return cella->get_width();
}

void Rullo::Inizializza(int vett[],int numstep)
{
	// Associo i parametri passati , cioè il vettore ed il numero di step
	num_step=numstep;
	for(int i=0;i<num_step;i++)
		vettore[i]=vett[i];

	// Creo i 3 simboli da visualizzare nel rullo 
	// + il 4 simbolo che deve subito entrare come successivo da sopra
	simboli1 = new CL_Sprite(vettore_simboli[vettore[1]].Nome, risorse);
	simboli2 = new CL_Sprite(vettore_simboli[vettore[0]].Nome, risorse);
	simboli3 = new CL_Sprite(vettore_simboli[vettore[MAX_BUFFER-1]].Nome, risorse);
	simboliAPP = new CL_Sprite(vettore_simboli[vettore[2]].Nome, risorse);
}

void Rullo::Update()
{
	// Se siamo all'inizio del gioco
	if(inizio==true)
		// Setto i 3 livelli Y dove disegnerò i simboli inizialmente
		SetLivelliYInizialiSimboli();
	else
	{
		// Se tutti i rulli devono scorrere
		if(STEPS<=NUM_STEPS_SCORRIMENTO_TOTALE)
			IncrementoStep();
		// Se non tutti i rulli devono scorrere (STEPS>NUM_STEPS_SCORRIMENTO_TOTALE)
		else
		{
			if(stop==false)
			{
				while(IND_STEP!=fermo_step)
				{
					IND_STEP++;
					IND_SIMBOLO_APP++;

					if(IND_STEP==MAX_BUFFER)
						IND_STEP=0;
					if(IND_SIMBOLO_APP==MAX_BUFFER)
						IND_SIMBOLO_APP=0;
				}
				for(int i=0;i<steps_da_fare;i++)
				{
					IND_STEP--;
					IND_SIMBOLO_APP--;

					if(IND_STEP==-1)
						IND_STEP=MAX_BUFFER-1;
					if(IND_SIMBOLO_APP==-1)
						IND_SIMBOLO_APP=MAX_BUFFER-1;
				}
				stop=true;
			}
			else
			{
				if(steps_da_fare>0)
					IncrementoStep();
				else
					SistemaSimboli();
			}
		}
	}
}

void Rullo::Disegna()
{
	// Disegno la struttura dei rulli (in questo caso 1 cella e 0 spazio tra celle)
	DisegnaStruttura(NUM_CELLE,SPAZIO_TRA_CELLE);

	simboli1->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,ySimb1,0);
	simboli2->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,ySimb2,0);
	simboli3->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,ySimb3,0);
	simboliAPP->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,ySimbAPP,0);

	coperturasup->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,y0,0);
	coperturainf->draw(xRullo+OFFSET_ORIZZONTALE_SIMBOLO,y4,0);
}

void Rullo::SetLivelliYInizialiSimboli()
{
	int alt=simboli1->get_height();

	y1=OFFSET_VERTICALE_SIMBOLO+yRullo;
	y2=y1+alt+OFFSET_VERTICALE_SIMBOLO;
	y3=y2+alt+OFFSET_VERTICALE_SIMBOLO;
	y0=y1-alt-OFFSET_VERTICALE_SIMBOLO;
	y4=y3+alt+OFFSET_VERTICALE_SIMBOLO;

	ySimb1=OFFSET_VERTICALE_SIMBOLO+yRullo;
	ySimb2=ySimb1+alt+OFFSET_VERTICALE_SIMBOLO;
	ySimb3=ySimb2+alt+OFFSET_VERTICALE_SIMBOLO;
	ySimbAPP=-200;

	yFinaleRullo=ySimb3+alt;
}

void Rullo::IncrementoStep()
{
	// alt identifica l'altezza del simbolo
	int alt=simboli1->get_height();

	// Aumento le coordinate y dei simboli per dare l'effetto di scorrimento
	ySimb1 += speed_simboli;
	ySimb2 += speed_simboli;
	ySimb3 += speed_simboli;		
	ySimbAPP += speed_simboli;	
			
	// Nel momento in cui l'ultimo simbolo comincia a sparire deve apparire il simbolo d'appoggio
	if(ySimb3==(y3+speed_simboli))
		ySimbAPP=y1-alt-OFFSET_VERTICALE_SIMBOLO+speed_simboli;

	// Quando il simbolo d'appoggio appare del tutto nel rullo
	// Incremento lo step del vettore e scambio i simboli facendo diventare quello d'appoggio il primo
	if(ySimbAPP>=y1)
	{
		// simboliAPP ----> simbolo1
		// simboli1 ----> simbolo2
		// simboli2 ----> simbolo3
		simboli3 = simboli2;
		simboli2 = simboli1;
		simboli1 = simboliAPP;
		// carico il nuovo simbolo d'appoggio
		simboliAPP = new CL_Sprite(vettore_simboli[vettore[IND_SIMBOLO_APP]].Nome, risorse);

		// "Pulisco" le coordinate y dei 4 simboli
		SetLivelliYInizialiSimboli();

		// Aggiorno gli indici degli step (IND_SIMBOLO_APP , IND_STEP e STEPS)
		AggiornaIndiciStep();
	}
}

void Rullo::AggiornaIndiciStep()
{
	// Incremento la var IND_SIMBOLO_APP che indica l'indice nel vettore degli step del prox simbolo d'appoggio
	IND_SIMBOLO_APP++;
	// Incremento la var IND_STEP che indica lo step visualizzato nel vettore degli step
	IND_STEP++;
	// Incremento la var STEPS che indica gli step totali (utilizzato per lo stop)
	STEPS++;

	// Se arrivo al massimo indice del vettore degli step riparto dal primo step
	if(IND_SIMBOLO_APP==MAX_BUFFER)
		IND_SIMBOLO_APP=0;
	if(IND_STEP==MAX_BUFFER)
		IND_STEP=0;

	if(stop==true)
		steps_da_fare--;
}

void Rullo::DisegnaStruttura(int num_celle, int spazio_tra_celle)
{
	int deltay=cella->get_height();
	int y=yRullo;

	for(int i=0;i<num_celle;i++)
	{
		cella->draw(xRullo,y,0);
		y=y+deltay+spazio_tra_celle;
	}
}

void Rullo::Scorri(float new_speed, int steps, int step_finale)
{
	// Creo i 3 simboli da visualizzare nel rullo 
	// + il 4 simbolo che deve subito entrare come successivo da sopra
	simboli1 = new CL_Sprite(vettore_simboli[vettore[1]].Nome, risorse);
	simboli2 = new CL_Sprite(vettore_simboli[vettore[0]].Nome, risorse);
	simboli3 = new CL_Sprite(vettore_simboli[vettore[MAX_BUFFER-1]].Nome, risorse);
	simboliAPP = new CL_Sprite(vettore_simboli[vettore[2]].Nome, risorse);

	// Inizializzo la var IND_SIMBOLO_APP che indica l'indice nel vettore degli step del prox simbolo d'appoggio
	IND_SIMBOLO_APP=3;
	// Inizializzo la var IND_STEP che indica lo step visualizzato nel vettore degli step
	IND_STEP=0;

	// Inizializzo la var STEPS che indica gli step totali (utilizzato per lo stop)
	STEPS=0;

	inizio=false;
	stop=false;

	speed_simboli=new_speed;
	steps_da_fare=steps;
	fermo_step=step_finale;
}

void Rullo::SistemaSimboli()
{
	int scostamento=5;

	if((steps_da_fare==0)||(steps_da_fare==-scostamento)||(steps_da_fare==-(scostamento*2)))
	{
		ySimb1=y1;
		ySimb2=y2;
		ySimb3=y3;
		ySimbAPP=-200;
		steps_da_fare--;
	}
	if(steps_da_fare>=-scostamento)
	{
		ySimb1++;
		ySimb2++;
		ySimb3++;
		ySimbAPP=-200;
		steps_da_fare--;
	}
	else
	{
		if(steps_da_fare>=-(scostamento*2))
		{
			ySimb1--;
			ySimb2--;
			ySimb3--;
			ySimbAPP=-200;
			steps_da_fare--;
		}
	}
}
